package com.sgcc.epri.dcloud.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.sgcc.epri.dcloud.mapper.dm.*;
import com.sgcc.epri.dcloud.pojo.*;
import com.sgcc.epri.dcloud.service.ComputeService;
import com.sgcc.epri.dcloud.util.ChoreUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;

@Service
public class ComputeServiceImpl implements ComputeService {

    private final Logger log =  LoggerFactory.getLogger(this.getClass());

    @Autowired
    private ComputationalLogic computationalLogic;

    @Autowired
    private TaskMapper taskMapper;

    @Autowired
    private TableHeadMapper tableHeadMapper;

    @Autowired
    private TreeMapper treeMapper;

    @Autowired
    private ManagementUnitMapper managementUnitMapper;

    @Autowired
    private Mapper mapper;

    @Autowired
    private AssetTypeParamCenterMapper assetTypeParamCenterMapper;

    @Autowired
    private ThreadPoolTaskExecutor thread;

    /**
     * 异步执行任务并记录任务状态
     * @param treeId
     * @return
     */
    @Override
    @Async("threadPoolTaskExecutor")
    public CompletableFuture<Result> startTask(String treeId, String dataType, String objectIds) {
        try{
            executeAsyncTask(treeId, dataType, objectIds);
        } catch (Exception e){
            e.printStackTrace();
            log.error("任务启动失败，树形结构ID:"+treeId+", 具体错误如下");
            log.error(""+e);
        }
        return CompletableFuture.completedFuture(Result.error("任务启动失败!"));
    }

    @Override
    public Result checkTaskCompletion(String treeId) {
        try{
            return Result.success(taskMapper.findTaskAllStatusById(treeId));
        }catch (Exception e){
            e.printStackTrace();
            log.error("查询任务状态失败！"+e);
            return Result.error("查询任务状态失败！");
        }
    }



    @Transactional
    @Async("threadPoolTaskExecutor")
    public Future<String> executeAsyncTask(String treeId, String dataTypeDimensionality, String objectIds) {

        long threadId = Thread.currentThread().getId();

        try{
            Map<String, Object> content = taskMapper.findTaskStatusById(treeId, dataTypeDimensionality, objectIds);
            if (content != null && content.get("status").toString().equals("executionIng")) {
                log.info("多次点击手动计算的同一任务是无效的，还请您耐心等待计算结果...");
                return null;
            }
            long startTime = System.currentTimeMillis();
            log.info("异步任务开始，线程ID：" + threadId+"，任务主键："+treeId+" "+dataTypeDimensionality+" "+objectIds);
            // upsert 操作数据库记录
            Integer count = taskMapper.update(threadId, treeId, "executionIng", dataTypeDimensionality, objectIds);
            if (count == 0) {
                taskMapper.insert(threadId, treeId, "executionIng", dataTypeDimensionality, objectIds);
            }

            //---------------------------任务开始-----------------------------
            List<CompletableFuture<Object>> futures = new ArrayList<>();

            // 本层树相关信息
            TreeNode treeNode = treeMapper.selectOne(new QueryWrapper<TreeNode>().eq("id", treeId));
            // 数据源
            QueryWrapper<ManagementUnit> muqw = new QueryWrapper<>();
            muqw.eq("parent_id",treeId);
            List<ManagementUnit> managementUnits = managementUnitMapper.selectList(muqw);
            // 表名
            Map<String, Object> tableNameMap = ChoreUtil.getTableNameMap(mapper.queryTableNameAll());

            QueryWrapper<TableHead> thqw = new QueryWrapper<>();
            thqw.isNotNull("object_id");
            thqw.isNotNull("index_names");
            thqw.isNotNull("data_type");
            if (!objectIds.equals("")) {
                String[] split = objectIds.split(",");
                List<String> strings = Arrays.asList(split);
                thqw.in("object_id", strings);
            }
            thqw.eq("parent_id_tree", treeId);
            // dky / nr / all
            if (dataTypeDimensionality.equals("0")) {
                thqw.eq("data_type","nr");
            } else if (dataTypeDimensionality.equals("1")) {
                thqw.eq("data_type", "dky");
                thqw.isNotNull("asset_names");
            } else if (dataTypeDimensionality.equals("")) {

            }
            List<TableHead> tableHeads = tableHeadMapper.selectList(thqw);
            for (TableHead tableHead : tableHeads) {
                // 哪一方的数据？
                String dataType = tableHead.getDataType();

                // 通过表头id查询指标
                List<Map<String, Object>> indexs = tableHeadMapper.queryIndexByType(tableHead.getId() + "");
                for (Map<String, Object> index : indexs) {
                    String indexId = index.get("id")+"";

                    QueryWrapper<AssetTypeParamCenter> apcq = new QueryWrapper<>();
                    apcq.eq("tablehead_id", tableHead.getId());
                    apcq.eq("index_id", indexId);
                    apcq.select("asset_id as asset_id");
                    List<AssetTypeParamCenter> params = assetTypeParamCenterMapper.selectList(apcq);

                    if (indexId.equals("1001") && dataType.equals("dky")) { // 电科院的接入率(AR)
                        CompletableFuture<Object> objectCompletableFuture = computationalLogic.dkyAccessRate(treeNode, managementUnits, params, tableNameMap, tableHead, null, indexId);
                        futures.add(objectCompletableFuture);
                    } else if (indexId.equals("1001") && dataType.equals("nr")) {// 南瑞的接入率(AR)
                        CompletableFuture<Object> objectCompletableFuture = computationalLogic.nrAccessRate(treeNode, managementUnits, params, tableHead, tableHead.getObjectId(), indexId);
                        futures.add(objectCompletableFuture);
                    } else if (indexId.equals("1002") && dataType.equals("dky")) { // 电科院的数据完整天数比例(FR)
                        CompletableFuture<Object> objectCompletableFuture = computationalLogic.dkyAccessRate(treeNode, managementUnits, params, tableNameMap, tableHead, null, indexId);
                        futures.add(objectCompletableFuture);
                    } else if (indexId.equals("1002") && dataType.equals("nr")) { // 南瑞的数据完整天数比例(FR)
                        CompletableFuture<Object> objectCompletableFuture = computationalLogic.nrAccessRate(treeNode, managementUnits, params, tableHead, tableHead.getObjectId(), indexId);
                        futures.add(objectCompletableFuture);
                    } else if (indexId.equals("1004") && dataType.equals("dky")) {// 电科院的应上送资产量(N)
                        CompletableFuture<Object> objectCompletableFuture = computationalLogic.dkyAccessRate(treeNode, managementUnits, params, tableNameMap, tableHead, null, indexId);
                        futures.add(objectCompletableFuture);
                    } else if (indexId.equals("1004") && dataType.equals("nr")) {// 南瑞的应上送资产量(N)
                        CompletableFuture<Object> objectCompletableFuture = computationalLogic.nrAccessRate(treeNode, managementUnits, params, tableHead, tableHead.getObjectId(), indexId);
                        futures.add(objectCompletableFuture);
                    } else if (indexId.equals("1003") && dataType.equals("dky")) {// 电科院的准确率(ACC)
                        CompletableFuture<Object> objectCompletableFuture = computationalLogic.accuracyRate(treeNode, managementUnits, params, tableNameMap, tableHead, null, indexId);
                        futures.add(objectCompletableFuture);
                        CompletableFuture<Object> objectCompletableFuture1 = computationalLogic.accuracyRateDetails(treeNode, managementUnits, params, tableNameMap, tableHead, null, indexId);
                        futures.add(objectCompletableFuture1);
                    }
                }
            }
            CompletableFuture<Void> allOf = CompletableFuture.allOf(futures.toArray(new CompletableFuture[]{new CompletableFuture<Object>()}));
            allOf.join();  // 阻塞直到所有任务完成
            //----------------------------任务结束----------------------------
            taskMapper.update(threadId, treeId, "executionCompleted", dataTypeDimensionality, objectIds);
            TreeNode updataTime = new TreeNode();
            updataTime.setId(Long.parseLong(treeId));
            updataTime.setUpdateTime(DateUtil.now());
            treeMapper.updateById(updataTime);
            log.info("异步任务结束，线程ID：" + threadId+"，任务主键："+treeId+" "+dataTypeDimensionality+" "+objectIds+"，耗时："+((System.currentTimeMillis() - startTime) / 1000) +"秒");
            return new AsyncResult<>("任务完成");
        }catch (Exception e){
            e.printStackTrace();
            log.error("任务执行失败，任务主键："+treeId+" "+dataTypeDimensionality+" "+objectIds+", 具体错误如下");
            log.error(""+e);
            taskMapper.update(threadId, treeId, "executionFailed", dataTypeDimensionality, objectIds);
            return new AsyncResult<>("任务执行失败");
        }

    }


}
